package com.brillilab.service.logic.crm;

import com.brillilab.common.alioss.OssFileEnum;
import com.brillilab.common.constant.ResultEnum;
import com.brillilab.common.entity.PageVo;
import com.brillilab.common.exceptions.BrillilabException;
import com.brillilab.domain.crm.kitRelateMethod.po.PublicMethodRelateReagent;
import com.brillilab.domain.crm.kitRelateMethod.vo.*;
import com.brillilab.domain.enums.common.BoolEnum;
import com.brillilab.domain.enums.method.ConvertMainSignType;
import com.brillilab.domain.enums.method.ConvertSignType;
import com.brillilab.domain.enums.method.MethodSourceEnum;
import com.brillilab.domain.enums.method.MethodTypeLevelEnum;
import com.brillilab.domain.po.global.GlobalKit;
import com.brillilab.domain.po.global.GlobalReagent;
import com.brillilab.domain.po.kit.ReagentType;
import com.brillilab.domain.po.method.Method;
import com.brillilab.domain.po.method.MethodPhase;
import com.brillilab.domain.po.method.MethodStep;
import com.brillilab.domain.po.method.MethodType;
import com.brillilab.domain.vo.common.KeyValue;
import com.brillilab.domain.vo.method.ConvertDTO;
import com.brillilab.domain.vo.method.IndexInfo;
import com.brillilab.service.core.crm.IKitRelateMethodService;
import com.brillilab.service.core.crm.IPublicMethodRelateReagentService;
import com.brillilab.service.core.global.IGlobalKitService;
import com.brillilab.service.core.global.IGlobalReagentService;
import com.brillilab.service.core.kit.IReagentTypeService;
import com.brillilab.service.core.method.IMethodPhaseService;
import com.brillilab.service.core.method.IMethodService;
import com.brillilab.service.core.method.IMethodStepService;
import com.brillilab.service.core.method.IMethodTypeService;
import com.brillilab.service.core.system.IFileManageService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author wuzhiyu
 * @Title: KitRelateMethodLogic
 * @ProjectName brill_lab
 * @Description: TODO
 * @date 2019/5/2813:58
 */
@Component
@Transactional
public class KitRelateMethodLogic {

    @Resource
    private IReagentTypeService reagentTypeService;
    @Resource
    private IGlobalKitService globalKitService;
    @Resource
    private IGlobalReagentService globalReagentService;
    @Resource
    private IMethodTypeService methodTypeService;
    @Resource
    private IMethodService methodService;
    @Resource
    private IMethodPhaseService methodPhaseService;
    @Resource
    private IMethodStepService methodStepService;
    @Resource
    private IKitRelateMethodService kitRelateMethodService;
    @Resource
    private IPublicMethodRelateReagentService publicMethodRelateReagentService;
    @Resource
    private IFileManageService fileManageService;

    public List<PublicReagentTypeVo> getPublicThirdReagentTypeList() {
        List<Long> typeListSelected = new ArrayList<>();
        typeListSelected.add(3L);
        typeListSelected.add(18L);
        typeListSelected.add(5L);
        typeListSelected.add(6L);
        typeListSelected.add(4L);
        typeListSelected.add(11L);
        typeListSelected.add(9L);
        typeListSelected.add(12L);
        typeListSelected.add(13L);
        typeListSelected.add(21L);
        typeListSelected.add(19L);
        typeListSelected.add(22L);
        List<ReagentType> typeList = reagentTypeService.getSelectedPublicReagentTypeList(typeListSelected);
        List<PublicReagentTypeVo> list = new ArrayList<>();
        for (ReagentType type : typeList) {
            PublicReagentTypeVo vo = new PublicReagentTypeVo();
            vo.setId(type.getId());
            vo.setName(type.getName());
            list.add(vo);
        }
        return list;
    }

    public PublicKitWithReagentInfo getKitWithReagentInfo(Long kitId) {
        GlobalKit globalKit = globalKitService.selectById(kitId);
        List<GlobalReagent> reagentList = globalReagentService.selectList(kitId);
        PublicKitWithReagentInfo kit = new PublicKitWithReagentInfo();
        kit.setId(globalKit.getId());
        kit.setName(globalKit.getName());
        List<PublicReagentInfo> list = new ArrayList<>();
        kit.setReagentInfoList(list);
        for (GlobalReagent r : reagentList) {
            PublicReagentInfo info = new PublicReagentInfo();
            info.setId(r.getId());
            info.setName(r.getName());
            list.add(info);
        }
        return kit;
    }

    public List<MethodType> getThirdPublicMethodType() {
        List<MethodType> allList = methodTypeService.listPublicMethodType();
        //List<PublicFirstMethodType> list = new ArrayList<>();
        //List<MethodType> firstList = allList.stream().filter(m -> MethodTypeLevelEnum.LevelFirst.getLevel().equals(m.getLevel())).collect(Collectors.toList());
        //List<MethodType> secondList = allList.stream().filter(m -> MethodTypeLevelEnum.LevelSecond.getLevel().equals(m.getLevel())).collect(Collectors.toList());
        List<MethodType> thirdList = allList.stream().filter(m -> MethodTypeLevelEnum.LevelThird.getLevel().equals(m.getLevel())).collect(Collectors.toList());
        //for (MethodType t : firstList) {
        //    PublicFirstMethodType firstType = new PublicFirstMethodType();
        //    firstType.setId(t.getId());
        //    firstType.setName(t.getName());
        //    List<PublicSecondMethodType> secondTypeList = new ArrayList<>();
        //    firstType.setSecondTypeList(secondTypeList);
        //    list.add(firstType);
        //    List<MethodType> thisSecondList = secondList.stream().filter(sec -> t.getId().equals(sec.getFirstId())).collect(Collectors.toList());
        //    thisSecondList.forEach(sec -> {
        //        PublicSecondMethodType secondType = new PublicSecondMethodType();
        //        secondType.setId(sec.getId());
        //        secondType.setName(sec.getName());
        //        List<PublicMethodType> thirdTypeList = new ArrayList<>();
        //        secondType.setThirdTypeList(thirdTypeList);
        //        secondTypeList.add(secondType);
        //        List<MethodType> thisThirdList = thirdList.stream().filter(third -> sec.getId().equals(third.getSecondId())).collect(Collectors.toList());
        //        thisThirdList.forEach(third -> {
        //            PublicMethodType thirdType = new PublicMethodType();
        //            thirdType.setId(third.getId());
        //            thirdType.setName(third.getName());
        //            thirdTypeList.add(thirdType);
        //        });
        //    });
        //}
        return thirdList;
    }

    public List<PublicFirstMethodType> getAllPublicMethodType() {
        List<MethodType> allList = methodTypeService.listPublicMethodType();
        List<PublicFirstMethodType> list = new ArrayList<>();
        List<MethodType> firstList = allList.stream().filter(m -> MethodTypeLevelEnum.LevelFirst.getLevel().equals(m.getLevel())).collect(Collectors.toList());
        List<MethodType> secondList = allList.stream().filter(m -> MethodTypeLevelEnum.LevelSecond.getLevel().equals(m.getLevel())).collect(Collectors.toList());
        List<MethodType> thirdList = allList.stream().filter(m -> MethodTypeLevelEnum.LevelThird.getLevel().equals(m.getLevel())).collect(Collectors.toList());
        for (MethodType t : firstList) {
            PublicFirstMethodType firstType = new PublicFirstMethodType();
            firstType.setId(t.getId());
            firstType.setName(t.getName());
            List<PublicSecondMethodType> secondTypeList = new ArrayList<>();
            firstType.setSecondTypeList(secondTypeList);
            list.add(firstType);
            List<MethodType> thisSecondList = secondList.stream().filter(sec -> t.getId().equals(sec.getFirstId())).collect(Collectors.toList());
            thisSecondList.forEach(sec -> {
                PublicSecondMethodType secondType = new PublicSecondMethodType();
                secondType.setId(sec.getId());
                secondType.setName(sec.getName());
                List<PublicMethodType> thirdTypeList = new ArrayList<>();
                secondType.setThirdTypeList(thirdTypeList);
                secondTypeList.add(secondType);
                List<MethodType> thisThirdList = thirdList.stream().filter(third -> sec.getId().equals(third.getSecondId())).collect(Collectors.toList());
                thisThirdList.forEach(third -> {
                    PublicMethodType thirdType = new PublicMethodType();
                    thirdType.setId(third.getId());
                    thirdType.setName(third.getName());
                    thirdTypeList.add(thirdType);
                });
            });
        }
        return list;
    }

    public Integer getKitRelateMethodStatistics() {
        return globalKitService.getKitRelateMethodStatistics();
    }

    public PublicMethodInfo getRelateMethodInfo(Long methodId) {
        Method method = methodService.getById(methodId);
        List<MethodPhase> phaseList = methodPhaseService.listByMethodId(methodId, BoolEnum.FALSE);
        List<MethodStep> stepList = methodStepService.listByMethodId(methodId, BoolEnum.FALSE);
        List<PublicMethodRelateReagent> relateReagentList = kitRelateMethodService.getRelateReagentListByMethodId(methodId);
        PublicMethodInfo methodInfo = new PublicMethodInfo();
        methodInfo.setId(method.getId());
        methodInfo.setAuthor(method.getAuthor());
        methodInfo.setDescription(method.getDescription());
        methodInfo.setLink(method.getLink());
        methodInfo.setName(method.getName());
        List<PublicPhaseInfo> phaseInfoList = new ArrayList<>();
        methodInfo.setPhaseList(phaseInfoList);
        if (!CollectionUtils.isEmpty(phaseList)) {
            phaseList.sort((x, y) -> {
                return x.getSort() - y.getSort();
            });
            phaseList.forEach(p -> {
                PublicPhaseInfo phaseInfo = new PublicPhaseInfo();
                phaseInfoList.add(phaseInfo);
                phaseInfo.setId(p.getId());
                phaseInfo.setName(p.getName());
                phaseInfo.setSort(p.getSort());
                phaseInfo.setTip(p.getTip());
                List<PublicStepInfo> stepInfoList = new ArrayList<>();
                phaseInfo.setStepList(stepInfoList);
                List<MethodStep> thisStepList = stepList.stream().filter(s -> s.getMethodPhaseId().equals(p.getId())).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(thisStepList)) {
                    thisStepList.sort((x, y) -> {
                        return x.getSort() - y.getSort();
                    });
                    thisStepList.forEach(s -> {
                        PublicStepInfo stepInfo = new PublicStepInfo();
                        stepInfoList.add(stepInfo);
                        stepInfo.setContent(s.getContent());
                        stepInfo.setId(s.getId());
                        stepInfo.setSort(s.getSort());
                        List<PublicMethodRelateReagent> stepRelateReagentList = relateReagentList.stream().filter(r -> r.getStepId().equals(s.getId())).collect(Collectors.toList());
                        stepInfo.setRelateReagentList(stepRelateReagentList);
                    });
                }
            });
        }
        return methodInfo;
    }

    public PageVo<PublicMethodListItem> getPublicMethodList(Boolean isOnStock, String namePrefix, int pageSize, int pageNum) {
        PageVo<Method> page = methodService.getPublicMethodList(isOnStock, namePrefix, pageSize, pageNum);
        List<MethodType> thirdMethodType = methodTypeService.getPublicThirdTypeList();
        PageVo<PublicMethodListItem> resultPage = new PageVo<>();
        BeanUtils.copyProperties(page, resultPage);
        List<PublicMethodListItem> result = new ArrayList<>();
        resultPage.setContent(result);
        if (!CollectionUtils.isEmpty(page.getContent())) {
            page.getContent().forEach(m -> {
                PublicMethodListItem item = new PublicMethodListItem();
                item.setName(m.getName());
                item.setId(m.getId());
                item.setState(m.getOnStock());
                MethodType third = thirdMethodType.stream().filter(t -> t.getId().equals(m.getMethodTypeId()) && t.getLevel().equals(MethodTypeLevelEnum.LevelThird.getLevel())).findFirst().get();
                item.setTypeName(third.getName());
                result.add(item);
            });
        }
        return resultPage;
    }

    public MethodConvertResultInfo convertMethod(PublicMethodConvertDto convertDto) {
        MethodConvertResultInfo resultInfo = new MethodConvertResultInfo();
        List<PublicPhaseInfo> methodPhaseDetailList = new ArrayList<>();
        resultInfo.setPhaseInfoList(methodPhaseDetailList);
        if (StringUtils.isEmpty(convertDto.getMethodText())) {
            return resultInfo;
        }
        String textContent = convertDto.getMethodText().replaceAll("\r", "");
        List<ConvertDTO> dtoList = new ArrayList<>();
        for (ConvertMainSignType main : ConvertMainSignType.values()) {
            for (ConvertSignType sign : ConvertSignType.values()) {
                ConvertDTO dto = new ConvertDTO(main, sign);
                for (int i = 0; i < dto.getMainSignList().size(); i++) {
                    dto.getIndexInfo(textContent, i);
                }
                dtoList.add(dto);
            }
        }
        List<ConvertDTO> result = dtoList.stream().filter(d -> !CollectionUtils.isEmpty(d.getIndexInfoList())).sorted((x, y) -> x.getIndexInfoList().get(0).getIndex() - y.getIndexInfoList().get(0).getIndex()).collect(Collectors.toList());
        //try {
        if (result.size() == 1) {
            ConvertDTO dto = result.get(0);
            PublicPhaseInfo methodPhaseDetail = new PublicPhaseInfo();
            methodPhaseDetailList.add(methodPhaseDetail);
            List<PublicStepInfo> methodStepDetailList = new ArrayList<>();
            methodPhaseDetail.setStepList(methodStepDetailList);
            setPhaseDtoInfo(textContent, methodPhaseDetail, new ConvertDTO(ConvertMainSignType.INT, ConvertSignType.DOT), dto);
            getStepConvertDto(textContent, dto, null, methodStepDetailList, convertDto.getReagentList());
        } else if (result.size() > 1) {
            ConvertDTO first = result.get(0);
            ConvertDTO second = result.get(1);
            if (first.getIndexInfoList().size() == 1) {
                PublicPhaseInfo methodPhaseDetail = new PublicPhaseInfo();
                methodPhaseDetailList.add(methodPhaseDetail);
                setPhaseDtoInfo(textContent, methodPhaseDetail, first, second);
                List<PublicStepInfo> methodStepDetailList = new ArrayList<>();
                methodPhaseDetail.setStepList(methodStepDetailList);
                getStepConvertDto(textContent, second, null, methodStepDetailList, convertDto.getReagentList());
            } else {
                for (int i = 0; i < first.getIndexInfoList().size(); i++) {
                    IndexInfo start = first.getIndexInfoList().get(i);
                    IndexInfo end = getEndIndexInfo(textContent, first, i);
                    String thisStr = textContent.substring(start.getIndex(), end.getIndex());
                    if (thisStr.startsWith("\n")) {
                        thisStr = thisStr.replaceFirst("\\s+", "");
                    }
                    PublicPhaseInfo methodPhaseDetail = new PublicPhaseInfo();
                    methodPhaseDetailList.add(methodPhaseDetail);
                    List<PublicStepInfo> methodStepDetailList = new ArrayList<>();
                    methodPhaseDetail.setStepList(methodStepDetailList);
                    ConvertDTO phaseDto = new ConvertDTO(first.getMainSignType(), first.getSignType());
                    phaseDto.regetIndexInfo(thisStr);
                    if (!phaseDto.getIndexInfoList().get(0).getSign().equals(start.getSign())) {
                        String signStr = phaseDto.getIndexInfoList().get(0).getSign().substring(0, phaseDto.getIndexInfoList().get(0).getSign().length() - 2);
                        String signv = phaseDto.getIndexInfoList().get(0).getSign().substring(phaseDto.getIndexInfoList().get(0).getSign().length() - 2, phaseDto.getIndexInfoList().get(0).getSign().length() - 1);
                        thisStr = thisStr.replace(phaseDto.getIndexInfoList().get(0).getSign(), signStr + " " + signv);
                        phaseDto.regetIndexInfo(thisStr);
                    }
                    ConvertDTO stepDto;
                    List<ConvertDTO> stepDtoList = new ArrayList<>();
                    for (ConvertMainSignType main : ConvertMainSignType.values()) {
                        for (ConvertSignType sign : ConvertSignType.values()) {
                            if (main.equals(first.getMainSignType()) && sign.equals(first.getSignType())) {

                            } else {
                                ConvertDTO dto = new ConvertDTO(main, sign);
                                for (int x = 0; x < dto.getMainSignList().size(); x++) {
                                    dto.getIndexInfo(thisStr, x);
                                }
                                stepDtoList.add(dto);
                            }
                        }
                    }
                    List<ConvertDTO> resultStep = stepDtoList.stream().filter(d -> !CollectionUtils.isEmpty(d.getIndexInfoList())).sorted((x, y) -> x.getIndexInfoList().get(0).getIndex() - y.getIndexInfoList().get(0).getIndex()).collect(Collectors.toList());
                    if (resultStep.size() > 0) {
                        stepDto = resultStep.get(0);
                    } else {
                        stepDto = new ConvertDTO(second.getMainSignType(), second.getSignType());
                        stepDto.regetIndexInfo(thisStr);
                    }
                    setPhaseDtoInfo(thisStr, methodPhaseDetail, phaseDto, stepDto);
                    getStepConvertDto(thisStr, stepDto, phaseDto, methodStepDetailList, convertDto.getReagentList());
                }
            }
        } else {
            PublicPhaseInfo methodPhaseDetail = new PublicPhaseInfo();
            methodPhaseDetailList.add(methodPhaseDetail);
            List<PublicStepInfo> methodStepDetailList = new ArrayList<>();
            PublicStepInfo step = new PublicStepInfo();
            step.setContent(textContent);
            methodStepDetailList.add(step);
            methodPhaseDetail.setStepList(methodStepDetailList);
        }
        //}catch (Exception ex)
        //{
        //    throw  new BrillilabException("请核对protocol内容是否正确");
        //}
        return resultInfo;
    }

    private void setPhaseDtoInfo(String thisStr, PublicPhaseInfo methodPhaseDetail, ConvertDTO phaseDto, ConvertDTO stepDto) {
        Integer firstNewLineIndex = thisStr.indexOf("\n");
        Integer oldLength = thisStr.length();
        Integer lenDiff = 0;
        if (firstNewLineIndex > -1 && phaseDto.getIndexInfoList().size() > 0 && firstNewLineIndex < phaseDto.getIndexInfoList().get(0).getIndex()) {
            thisStr = thisStr.replaceFirst("\\s+", "");
            lenDiff = oldLength - thisStr.length();
        }
        firstNewLineIndex = thisStr.indexOf("\n");
        if (phaseDto.getIndexInfoList().size() > 1) {
            if (stepDto.getIndexInfoList().size() > 0) {
                if (firstNewLineIndex > -1 && firstNewLineIndex < (stepDto.getIndexInfoList().get(0).getIndex() - lenDiff) && (phaseDto.getIndexInfoList().get(0).getIndex() - lenDiff + phaseDto.getIndexInfoList().get(0).getSignLength()) < firstNewLineIndex) {
                    methodPhaseDetail.setName(thisStr.substring(phaseDto.getIndexInfoList().get(0).getIndex() - lenDiff + phaseDto.getIndexInfoList().get(0).getSignLength(), firstNewLineIndex).replaceAll("\n", ""));
                    methodPhaseDetail.setTip(thisStr.substring(firstNewLineIndex, stepDto.getIndexInfoList().get(0).getIndex() - lenDiff).replaceAll("\n", ""));
                } else {
                    methodPhaseDetail.setName(thisStr.substring(phaseDto.getIndexInfoList().get(0).getIndex() - lenDiff + phaseDto.getIndexInfoList().get(0).getSignLength(), stepDto.getIndexInfoList().get(0).getIndex() - lenDiff).replaceAll("\n", ""));
                }
            } else {
                if (firstNewLineIndex > -1 && firstNewLineIndex < (phaseDto.getIndexInfoList().get(1).getIndex() - lenDiff)) {
                    methodPhaseDetail.setName(thisStr.substring(phaseDto.getIndexInfoList().get(0).getIndex() - lenDiff + phaseDto.getIndexInfoList().get(0).getSignLength(), firstNewLineIndex).replaceAll("\n", ""));
                    //methodPhaseDetail.setTip(thisStr.substring(firstNewLineIndex, phaseDto.getIndexInfoList().get(1).getIndex() - lenDiff));
                    PublicStepInfo step = new PublicStepInfo();
                    step.setContent(thisStr.substring(firstNewLineIndex, phaseDto.getIndexInfoList().get(1).getIndex() - lenDiff).replaceAll("\n", ""));
                    methodPhaseDetail.getStepList().add(step);
                } else {
                    methodPhaseDetail.setName(thisStr.substring(phaseDto.getIndexInfoList().get(0).getIndex() - lenDiff + phaseDto.getIndexInfoList().get(0).getSignLength(), phaseDto.getIndexInfoList().get(1).getIndex() - lenDiff).replaceAll("\n", ""));
                }
            }
        } else if (phaseDto.getIndexInfoList().size() == 1) {
            if (stepDto.getIndexInfoList().size() > 0) {
                if (firstNewLineIndex > -1 && firstNewLineIndex < (stepDto.getIndexInfoList().get(0).getIndex() - lenDiff)) {
                    methodPhaseDetail.setName(thisStr.substring(phaseDto.getIndexInfoList().get(0).getIndex() - lenDiff + phaseDto.getIndexInfoList().get(0).getSignLength(), firstNewLineIndex).replaceAll("\n", ""));
                    methodPhaseDetail.setTip(thisStr.substring(firstNewLineIndex, stepDto.getIndexInfoList().get(0).getIndex() - lenDiff).replaceAll("\n", ""));
                } else {
                    if (phaseDto.getIndexInfoList().get(0).getSign().equals(stepDto.getIndexInfoList().get(0).getSign()) && firstNewLineIndex > -1) {
                        methodPhaseDetail.setName(thisStr.substring(phaseDto.getIndexInfoList().get(0).getIndex() - lenDiff + phaseDto.getIndexInfoList().get(0).getSignLength(), firstNewLineIndex).replaceAll("\n", ""));
                    } else {
                        methodPhaseDetail.setName(thisStr.substring(phaseDto.getIndexInfoList().get(0).getIndex() - lenDiff + phaseDto.getIndexInfoList().get(0).getSignLength(), stepDto.getIndexInfoList().get(0).getIndex() - lenDiff).replaceAll("\n", ""));
                    }
                }
            } else {
                if (firstNewLineIndex > -1 && firstNewLineIndex < thisStr.length()) {
                    if (phaseDto.getIndexInfoList().get(0).getIndex() - lenDiff + phaseDto.getIndexInfoList().get(0).getSignLength() < firstNewLineIndex) {
                        methodPhaseDetail.setName(thisStr.substring(phaseDto.getIndexInfoList().get(0).getIndex() - lenDiff + phaseDto.getIndexInfoList().get(0).getSignLength(), firstNewLineIndex));
                    } else {
                        methodPhaseDetail.setName(thisStr.substring(0, firstNewLineIndex).replaceAll("\n", ""));
                    }
                    PublicStepInfo step = new PublicStepInfo();
                    step.setContent(thisStr.substring(firstNewLineIndex).replaceAll("\n", ""));
                    methodPhaseDetail.getStepList().add(step);
                } else {
                    methodPhaseDetail.setName(thisStr.substring(phaseDto.getIndexInfoList().get(0).getIndex() - lenDiff + phaseDto.getIndexInfoList().get(0).getSignLength()).replaceAll("\n", ""));
                }
            }
        } else {
            if (stepDto.getIndexInfoList().size() > 0) {
                if (firstNewLineIndex > -1 && firstNewLineIndex < (stepDto.getIndexInfoList().get(0).getIndex() - lenDiff)) {
                    methodPhaseDetail.setName(thisStr.substring(0, firstNewLineIndex).replaceAll("\n", ""));
                    methodPhaseDetail.setTip(thisStr.substring(firstNewLineIndex, stepDto.getIndexInfoList().get(0).getIndex() - lenDiff).replaceAll("\n", ""));
                } else {
                    methodPhaseDetail.setName(thisStr.substring(0, stepDto.getIndexInfoList().get(0).getIndex() - lenDiff).replaceAll("\n", ""));
                }
            } else {
                if (firstNewLineIndex > -1 && firstNewLineIndex < thisStr.length()) {
                    methodPhaseDetail.setName(thisStr.substring(0, firstNewLineIndex).replaceAll("\n", ""));
                    //methodPhaseDetail.setTip(thisStr.substring(firstNewLineIndex));
                    PublicStepInfo step = new PublicStepInfo();
                    step.setContent(thisStr.substring(firstNewLineIndex).replaceAll("\n", ""));
                    methodPhaseDetail.getStepList().add(step);
                } else {
                    methodPhaseDetail.setName(thisStr.replaceAll("\n", ""));
                }
            }
        }
    }

    private IndexInfo getEndIndexInfo(String textContent, ConvertDTO dto, int i) {
        IndexInfo end;
        if (i == dto.getIndexInfoList().size() - 1) {
            end = new IndexInfo();
            end.setIndex(textContent.length());
        } else {
            end = dto.getIndexInfoList().get(i + 1);
        }
        return end;
    }

    private void getStepConvertDto(String textContent, ConvertDTO stepDto, ConvertDTO
            phaseDto, List<PublicStepInfo> methodStepDetailList, List<PublicReagentInfo> reagentList) {
        for (int i = 0; i < stepDto.getIndexInfoList().size(); i++) {
            IndexInfo start = stepDto.getIndexInfoList().get(i);
            IndexInfo end = getEndIndexInfo(textContent, stepDto, i);
            PublicStepInfo stepContentDto = new PublicStepInfo();
            List<PublicMethodRelateReagent> relateReagentList = new ArrayList<>();
            stepContentDto.setRelateReagentList(relateReagentList);
            String content = textContent.substring(start.getIndex(), end.getIndex());
            setStepContent(phaseDto, start, stepContentDto, content, reagentList);
            methodStepDetailList.add(stepContentDto);
        }
    }

    private void setStepContent(ConvertDTO phaseDto, IndexInfo start, PublicStepInfo stepContentDto, String
            content, List<PublicReagentInfo> reagentList) {
        String trimStr = content.replaceFirst("\\s+", "");
        if (phaseDto == null) {
            if (start.getSignLength() != null && start.getSignLength() < trimStr.length()) {
                stepContentDto.setContent(trimStr.substring(start.getSignLength()).replaceAll("\n", ""));
            } else {
                stepContentDto.setContent(trimStr.replaceAll("\n", ""));
            }
        } else {
            stepContentDto.setContent(trimStr.substring(start.getSignLength()).replaceAll("\n", ""));
        }
        if (!StringUtils.isEmpty(stepContentDto.getContent())) {
            for (PublicReagentInfo reagent : reagentList) {
                Pattern p = Pattern.compile("(" + reagent.getName().trim() + ")", Pattern.CASE_INSENSITIVE);
                Matcher m = p.matcher(stepContentDto.getContent());
                List<Integer> indexList = new ArrayList<>();
                while (m.find()) {
                    indexList.add(m.end());
                }
                if (!CollectionUtils.isEmpty(indexList)) {
                    StringBuilder sb = new StringBuilder(stepContentDto.getContent());
                    for (Integer i = indexList.size() - 1; i >= 0; i--) {
                        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
                        sb.insert(indexList.get(i), "#${[reagent]<" + uuid + ">}$#");
                        PublicMethodRelateReagent newReagent = new PublicMethodRelateReagent();
                        newReagent.setReagentName(reagent.getName());
                        newReagent.setGlobalReagentId(reagent.getId());
                        newReagent.setUuid(uuid);
                        newReagent.setId((long) i);
                        stepContentDto.getRelateReagentList().add(newReagent);
                    }
                    stepContentDto.getRelateReagentList().sort((x, y) -> {
                        return (int) (y.getId() - x.getId());
                    });
                    stepContentDto.setContent(sb.toString().replaceAll("\n", ""));
                }
            }
        }
    }

    public boolean savePublicMethod(PublicMethodInfo method) {
        Assert.isTrue(method.getIsCommon()==null||(method.getIsCommon().equals(1)&&method.getGlobalKitId()!=null),"非法参数");
        Method newMethod = new Method();
        BeanUtils.copyProperties(method, newMethod);
        newMethod.setOnStock(BoolEnum.FALSE.getValue());
        newMethod.setFromType(MethodSourceEnum.CREATE.getSourceType());
        newMethod.setVersion(0);
        newMethod.setCurrent(1);
        methodService.saveMethodAndUpdateInitId(newMethod);
        if (method.getGlobalKitId() != null) {
            GlobalKit gk = new GlobalKit();
            gk.setPdfTxt(method.getPdfTxt());
            gk.setId(method.getGlobalKitId());
            gk.setRelateMethodId(newMethod.getId());
            globalKitService.updateById(gk);
        }
        if (!CollectionUtils.isEmpty(method.getPhaseList())) {
            method.getPhaseList().forEach(p -> {
                MethodPhase phase = new MethodPhase();
                BeanUtils.copyProperties(p, phase);
                phase.setMethodId(newMethod.getId());
                methodPhaseService.savePhaseAndUpdateInitId(phase, MethodSourceEnum.CREATE.getSourceType());
                if (!CollectionUtils.isEmpty(p.getStepList())) {
                    p.getStepList().forEach(s -> {
                        MethodStep step = new MethodStep();
                        BeanUtils.copyProperties(s, step);
                        step.setMethodId(newMethod.getId());
                        step.setMethodPhaseId(phase.getId());
                        methodStepService.saveStepAndUpdateInitId(step, MethodSourceEnum.CREATE.getSourceType());
                        if (!CollectionUtils.isEmpty(s.getRelateReagentList())) {
                            s.getRelateReagentList().forEach(reagent -> {
                                reagent.setMethodId(newMethod.getId());
                                reagent.setPhaseId(phase.getId());
                                reagent.setStepId(step.getId());
                                publicMethodRelateReagentService.saveRelateReagent(reagent);
                            });
                        }
                    });
                }
            });
        }
        if (!CollectionUtils.isEmpty(method.getAttachUrlList())) {
            fileManageService.saveFilePublicUrlList(method.getAttachUrlList(), newMethod.getId(), OssFileEnum.PublicMethod);
        }
        return true;
    }

    public boolean onStock(KeyValue<Long, Integer> value) {
        Method method = new Method();
        method.setId(value.getKey());
        method.setOnStock(value.getValue());
        return methodService.updateById(method);
    }

    public MethodConvertResultInfo previewConvert(PublicMethodConvertDto convertDto) {
        MethodConvertResultInfo resultInfo = new MethodConvertResultInfo();
        List<IndexInfo> indexList = new ArrayList<>();
        List<PublicPhaseInfo> methodPhaseDetailList = new ArrayList<>();
        resultInfo.setPhaseInfoList(methodPhaseDetailList);
        if (StringUtils.isEmpty(convertDto.getMethodText())) {
            return resultInfo;
        }
        String textContent = convertDto.getMethodText().replaceAll("\r", "");
        List<ConvertDTO> dtoList = new ArrayList<>();
        for (ConvertMainSignType main : ConvertMainSignType.values()) {
            for (ConvertSignType sign : ConvertSignType.values()) {
                ConvertDTO dto = new ConvertDTO(main, sign);
                for (int i = 0; i < dto.getMainSignList().size(); i++) {
                    dto.getIndexInfo(textContent, i);
                }
                dtoList.add(dto);
            }
        }
        List<ConvertDTO> result = dtoList.stream().filter(d -> !CollectionUtils.isEmpty(d.getIndexInfoList())).sorted((x, y) -> x.getIndexInfoList().get(0).getIndex() - y.getIndexInfoList().get(0).getIndex()).collect(Collectors.toList());
        if (result.size() > 0) {
            ConvertDTO firstDto = result.get(0);
            indexList.addAll(firstDto.getIndexInfoList());
            for (int i = 0; i < firstDto.getIndexInfoList().size(); i++) {
                IndexInfo start = firstDto.getIndexInfoList().get(i);
                IndexInfo end = getEndIndexInfo(textContent, firstDto, i);
                String thisStr = textContent.substring(start.getIndex() + start.getSignLength(), end.getIndex());
                ConvertDTO phaseDto = new ConvertDTO(firstDto.getMainSignType(), firstDto.getSignType());
                phaseDto.regetIndexInfo(thisStr);
                List<ConvertDTO> stepDtoList = new ArrayList<>();
                for (ConvertMainSignType main : ConvertMainSignType.values()) {
                    for (ConvertSignType sign : ConvertSignType.values()) {
                        if (main.equals(firstDto.getMainSignType()) && sign.equals(firstDto.getSignType())) {

                        } else {
                            ConvertDTO dto = new ConvertDTO(main, sign);
                            for (int x = 0; x < dto.getMainSignList().size(); x++) {
                                dto.getIndexInfo(thisStr, x);
                            }
                            stepDtoList.add(dto);
                        }
                    }
                }
                List<ConvertDTO> resultStep = stepDtoList.stream().filter(d -> !CollectionUtils.isEmpty(d.getIndexInfoList())).sorted((x, y) -> x.getIndexInfoList().get(0).getIndex() - y.getIndexInfoList().get(0).getIndex()).collect(Collectors.toList());
                if (resultStep.size() > 0) {
                    for (ConvertDTO stepDto : resultStep) {
                        for (IndexInfo ii : stepDto.getIndexInfoList()) {
                            ii.setIndex(ii.getIndex() + start.getIndex() + start.getSignLength());
                        }
                        indexList.addAll(stepDto.getIndexInfoList());
                    }
                }
            }
        }
        resultInfo.setSplitIndexList(indexList);
        MethodConvertResultInfo finalResult = new MethodConvertResultInfo();
        finalResult.setSplitIndexList(new ArrayList<>());
        for (int m=0;m<resultInfo.getSplitIndexList().size();m++){
            IndexInfo ii = resultInfo.getSplitIndexList().get(m);
            if(!finalResult.getSplitIndexList().stream().anyMatch(o->o.getSign().equals(ii.getSign())&o.getIndex().equals(ii.getIndex()))){
                finalResult.getSplitIndexList().add(ii);
            }
        }
        finalResult.getSplitIndexList().sort((x, y) -> {
            return y.getIndex() - x.getIndex();
        });
        return finalResult;
    }

    public boolean addPublicThirdMethodType(MethodType type) {
        MethodType secondType = methodTypeService.selectOneById(type.getSecondId());
        if (secondType.getUserId() != null) {
            throw new BrillilabException(ResultEnum.DATA_NOT_EXIST);
        }
        type.setFirstId(secondType.getFirstId());
        type.setUserId(null);
        type.setLevel(MethodTypeLevelEnum.LevelThird.getLevel());
        return methodTypeService.add(type);
    }

    public boolean updateReagentAlias(KeyValue<Long, String> data) {
        GlobalReagent reagent = globalReagentService.selectById(data.getKey());
        if (reagent == null) {
            throw new BrillilabException(ResultEnum.DATA_NOT_EXIST);
        }
        GlobalReagent update = new GlobalReagent();
        update.setId(data.getKey());
        update.setAlias(data.getValue());
        return globalReagentService.updateById(update);
    }

    public boolean batchRelateMethod(KeyValue<Long, List<Long>> data) {
        Method method = methodService.getById(data.getKey());
        Assert.notNull(method, ResultEnum.DATA_NOT_EXIST.getMessage());
        Assert.isTrue(method.getUserId() == null, ResultEnum.DATA_NOT_EXIST.getMessage());
        return globalKitService.batchRelateMethod(data.getValue(), method.getId());
    }

    public boolean setNoProtocol(Long globalKitId) {
        GlobalKit kit = new GlobalKit();
        kit.setId(globalKitId);
        kit.setHasSplitSign(BoolEnum.FALSE.getValue());
        return globalKitService.updateById(kit);
    }
}
